package org.microframework.base.core.datasource.example;

import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
// 注意：使用时需要确保正确引入以下依赖
// import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * Seata分布式事务与JFinal ActiveRecord集成示例
 * 
 * 使用JFinal ActiveRecord而非JdbcTemplate进行数据操作
 * 使得分布式事务能够与JFinal的本地事务机制无缝集成
 * 
 * 注意：此文件仅为示例代码，实际使用时需确保已正确引入Seata依赖:
 * io.seata:seata-spring-boot-starter
 */
//@Service
public class SeataActiveRecordDemo {
    
    @Autowired
    private RemoteOrderService orderService; // 远程服务调用接口
    
    @Autowired
    private RemoteInventoryService inventoryService; // 远程服务调用接口

    /**
     * 分布式事务示例 - 下单业务
     * 
     * 通过@GlobalTransactional注解定义分布式事务边界
     * 整个方法执行过程中涉及多个微服务和数据库操作将作为一个事务整体
     * 任何一个操作失败都会导致整体回滚
     * 
     * 实际使用时应添加注解: @GlobalTransactional(name = "create-order-tx", timeoutMills = 60000)
     */
    // @GlobalTransactional(name = "create-order-tx", timeoutMills = 60000)
    public void createOrder(String userId, String productId, int quantity) {
        // 步骤1: 创建订单（当前服务）- 使用JFinal ActiveRecord
        Record order = new Record();
        order.set("user_id", userId);
        order.set("product_id", productId);
        order.set("quantity", quantity);
        order.set("status", "CREATED");
        Db.save("t_order", order);
        
        // 步骤2: 远程调用 - 扣减库存（库存服务）
        boolean inventoryResult = inventoryService.reduceInventory(productId, quantity);
        if (!inventoryResult) {
            throw new RuntimeException("库存不足，无法下单");
        }
        
        // 步骤3: 远程调用 - 扣减账户余额（用户服务）
        boolean paymentResult = orderService.makePayment(userId, calculateAmount(productId, quantity));
        if (!paymentResult) {
            throw new RuntimeException("用户余额不足，支付失败");
        }
        
        // 步骤4: 更新订单状态为已支付（当前服务）- 使用JFinal ActiveRecord
        Db.update("UPDATE t_order SET status = ? WHERE user_id = ? AND product_id = ?", 
                 "PAID", userId, productId);
        
        // 如果整个过程中任何一步失败，Seata会自动回滚所有操作
        // 包括远程服务中的数据库操作
    }
    
    /**
     * 使用JFinal Model API的更简洁写法
     * 
     * 实际使用时应添加注解: @GlobalTransactional(name = "create-order-model-tx", timeoutMills = 60000)
     */
    // @GlobalTransactional(name = "create-order-model-tx", timeoutMills = 60000)
    public void createOrderWithModel(String userId, String productId, int quantity) {
        // 使用JFinal Model API - 假设已经定义了Order模型类
        Order order = new Order();
        order.setUserId(userId);
        order.setProductId(productId);
        order.setQuantity(quantity);
        order.setStatus("CREATED");
        order.save();
        
        // 远程服务调用（略，同上）
        
        // 更新订单状态 - 使用JFinal Model API
        Order.dao.findFirst("SELECT * FROM t_order WHERE user_id=? AND product_id=?", userId, productId)
                .setStatus("PAID")
                .update();
    }
    
    /**
     * 计算订单金额
     */
    private double calculateAmount(String productId, int quantity) {
        // 实际应用中可能会查询商品价格等信息
        return 100.0 * quantity;
    }
    
    /**
     * 远程订单服务接口（示例）
     */
    public interface RemoteOrderService {
        boolean makePayment(String userId, double amount);
    }
    
    /**
     * 远程库存服务接口（示例）
     */
    public interface RemoteInventoryService {
        boolean reduceInventory(String productId, int quantity);
    }
    
    /**
     * JFinal模型类示例 - 订单模型
     * 在实际应用中，应该在单独的Model类中定义
     */
    public static class Order extends com.jfinal.plugin.activerecord.Model<Order> {
        private static final long serialVersionUID = 1L;
        public static final Order dao = new Order().dao();
        
        public String getUserId() { return getStr("user_id"); }
        public Order setUserId(String userId) { set("user_id", userId); return this; }
        
        public String getProductId() { return getStr("product_id"); }
        public Order setProductId(String productId) { set("product_id", productId); return this; }
        
        public Integer getQuantity() { return getInt("quantity"); }
        public Order setQuantity(Integer quantity) { set("quantity", quantity); return this; }
        
        public String getStatus() { return getStr("status"); }
        public Order setStatus(String status) { set("status", status); return this; }
    }
} 